import sharp from 'sharp';
import fs from 'fs/promises';
import path from 'path';
import { app } from 'electron';

/**
 * 缩略图尺寸配置
 */
export const THUMBNAIL_SIZES = {
  small: 150,
  medium: 300,
  large: 600
} as const;

export type ThumbnailSize = keyof typeof THUMBNAIL_SIZES;

/**
 * 缩略图生成选项
 */
export interface ThumbnailOptions {
  size?: ThumbnailSize | number;
  quality?: number;
  format?: 'jpeg' | 'png' | 'webp';
  background?: string;
  fit?: 'cover' | 'contain' | 'fill' | 'inside' | 'outside';
}

/**
 * 缩略图信息接口
 */
export interface ThumbnailInfo {
  path: string;
  size: number;
  width: number;
  height: number;
  format: string;
  filesize: number;
  createdAt: Date;
}

/**
 * 缩略图生成器类
 */
export class ThumbnailGenerator {
  private thumbnailDir: string;
  private cache = new Map<string, ThumbnailInfo>();

  constructor() {
    // 获取缩略图存储目录
    const userDataPath = app.getPath('userData');
    this.thumbnailDir = path.join(userDataPath, 'thumbnails');
    
    // 确保缩略图目录存在
    this.ensureThumbnailDirectory();
  }

  /**
   * 确保缩略图目录存在
   */
  private async ensureThumbnailDirectory(): Promise<void> {
    try {
      await fs.mkdir(this.thumbnailDir, { recursive: true });
      
      // 创建不同尺寸的子目录
      for (const size of Object.keys(THUMBNAIL_SIZES)) {
        await fs.mkdir(path.join(this.thumbnailDir, size), { recursive: true });
      }
    } catch (error) {
      console.error('创建缩略图目录失败:', error);
      throw error;
    }
  }

  /**
   * 生成缩略图
   */
  public async generateThumbnail(
    imagePath: string,
    options: ThumbnailOptions = {}
  ): Promise<ThumbnailInfo> {
    const {
      size = 'medium',
      quality = 85,
      format = 'jpeg',
      background = '#ffffff',
      fit = 'cover'
    } = options;

    console.log(`正在生成缩略图: ${imagePath}`);

    try {
      // 检查原始文件是否存在
      await this.checkFileExists(imagePath);

      // 获取缩略图路径
      const thumbnailPath = this.getThumbnailPath(imagePath, size, format);
      
      // 检查缩略图是否已存在且是最新的
      const existingThumbnail = await this.checkExistingThumbnail(imagePath, thumbnailPath);
      if (existingThumbnail) {
        console.log(`使用现有缩略图: ${thumbnailPath}`);
        return existingThumbnail;
      }

      // 获取目标尺寸
      const targetSize = typeof size === 'number' ? size : THUMBNAIL_SIZES[size];

      // 生成缩略图
      const sharpInstance = sharp(imagePath);
      
      // 获取原始图片信息
      const metadata = await sharpInstance.metadata();
      
      // 配置 Sharp 处理选项
      let processedImage = sharpInstance
        .resize(targetSize, targetSize, {
          fit,
          background,
          withoutEnlargement: true
        });

      // 设置输出格式和质量
      switch (format) {
        case 'jpeg':
          processedImage = processedImage.jpeg({ quality, progressive: true });
          break;
        case 'png':
          processedImage = processedImage.png({ quality, progressive: true });
          break;
        case 'webp':
          processedImage = processedImage.webp({ quality });
          break;
      }

      // 确保缩略图目录存在
      await fs.mkdir(path.dirname(thumbnailPath), { recursive: true });

      // 保存缩略图
      await processedImage.toFile(thumbnailPath);

      // 获取生成的缩略图信息
      const thumbnailStats = await fs.stat(thumbnailPath);
      const thumbnailMetadata = await sharp(thumbnailPath).metadata();

      const thumbnailInfo: ThumbnailInfo = {
        path: thumbnailPath,
        size: targetSize,
        width: thumbnailMetadata.width || 0,
        height: thumbnailMetadata.height || 0,
        format,
        filesize: thumbnailStats.size,
        createdAt: thumbnailStats.birthtime
      };

      // 添加到缓存
      this.cache.set(this.getCacheKey(imagePath, size, format), thumbnailInfo);

      console.log(`缩略图生成完成: ${thumbnailPath}`);
      return thumbnailInfo;

    } catch (error) {
      console.error(`生成缩略图失败: ${imagePath}`, error);
      throw error;
    }
  }

  /**
   * 批量生成缩略图
   */
  public async generateThumbnails(
    imagePaths: string[],
    options: ThumbnailOptions = {},
    onProgress?: (current: number, total: number, currentPath: string) => void
  ): Promise<ThumbnailInfo[]> {
    console.log(`开始批量生成 ${imagePaths.length} 个缩略图`);

    const results: ThumbnailInfo[] = [];
    const errors: { path: string; error: string }[] = [];

    for (let i = 0; i < imagePaths.length; i++) {
      const imagePath = imagePaths[i];
      
      try {
        // 调用进度回调
        if (onProgress) {
          onProgress(i + 1, imagePaths.length, imagePath);
        }

        const thumbnailInfo = await this.generateThumbnail(imagePath, options);
        results.push(thumbnailInfo);

      } catch (error) {
        console.error(`批量生成缩略图失败: ${imagePath}`, error);
        errors.push({
          path: imagePath,
          error: error instanceof Error ? error.message : String(error)
        });
      }
    }

    if (errors.length > 0) {
      console.warn(`批量生成完成，但有 ${errors.length} 个文件失败:`, errors);
    }

    console.log(`批量生成缩略图完成: 成功 ${results.length}，失败 ${errors.length}`);
    return results;
  }

  /**
   * 获取缩略图路径
   */
  public getThumbnailPath(
    imagePath: string,
    size: ThumbnailSize | number = 'medium',
    format: string = 'jpeg'
  ): string {
    // 生成基于原始文件路径的哈希值作为文件名
    const hash = this.generatePathHash(imagePath);
    const sizeStr = typeof size === 'number' ? size.toString() : size;
    const filename = `${hash}.${format}`;
    
    return path.join(this.thumbnailDir, sizeStr, filename);
  }

  /**
   * 检查缩略图是否存在
   */
  public async thumbnailExists(
    imagePath: string,
    size: ThumbnailSize | number = 'medium',
    format: string = 'jpeg'
  ): Promise<boolean> {
    const thumbnailPath = this.getThumbnailPath(imagePath, size, format);
    
    try {
      await fs.access(thumbnailPath);
      return true;
    } catch {
      return false;
    }
  }

  /**
   * 删除缩略图
   */
  public async deleteThumbnail(
    imagePath: string,
    size?: ThumbnailSize | number,
    format?: string
  ): Promise<void> {
    try {
      if (size && format) {
        // 删除特定尺寸和格式的缩略图
        const thumbnailPath = this.getThumbnailPath(imagePath, size, format);
        await fs.unlink(thumbnailPath);
        
        // 从缓存中移除
        const cacheKey = this.getCacheKey(imagePath, size, format);
        this.cache.delete(cacheKey);
        
        console.log(`已删除缩略图: ${thumbnailPath}`);
      } else {
        // 删除所有相关的缩略图
        const hash = this.generatePathHash(imagePath);
        
        for (const sizeKey of Object.keys(THUMBNAIL_SIZES)) {
          const sizeDir = path.join(this.thumbnailDir, sizeKey);
          
          try {
            const files = await fs.readdir(sizeDir);
            const matchingFiles = files.filter(file => file.startsWith(hash));
            
            for (const file of matchingFiles) {
              const filePath = path.join(sizeDir, file);
              await fs.unlink(filePath);
              console.log(`已删除缩略图: ${filePath}`);
            }
          } catch (error) {
            // 忽略目录不存在的错误
            if (error instanceof Error && 'code' in error && error.code !== 'ENOENT') {
              console.error(`删除缩略图失败: ${sizeDir}`, error);
            }
          }
        }

        // 清理缓存
        for (const key of this.cache.keys()) {
          if (key.includes(imagePath)) {
            this.cache.delete(key);
          }
        }
      }
    } catch (error) {
      console.error(`删除缩略图失败: ${imagePath}`, error);
      throw error;
    }
  }

  /**
   * 清理所有缩略图
   */
  public async clearAllThumbnails(): Promise<void> {
    try {
      console.log('正在清理所有缩略图...');
      
      // 删除缩略图目录
      await fs.rm(this.thumbnailDir, { recursive: true, force: true });
      
      // 重新创建目录
      await this.ensureThumbnailDirectory();
      
      // 清空缓存
      this.cache.clear();
      
      console.log('所有缩略图已清理完成');
    } catch (error) {
      console.error('清理缩略图失败:', error);
      throw error;
    }
  }

  /**
   * 获取缩略图统计信息
   */
  public async getStats(): Promise<{
    totalThumbnails: number;
    totalSize: number;
    sizeBreakdown: Record<string, { count: number; size: number }>;
  }> {
    const stats = {
      totalThumbnails: 0,
      totalSize: 0,
      sizeBreakdown: {} as Record<string, { count: number; size: number }>
    };

    try {
      for (const sizeKey of Object.keys(THUMBNAIL_SIZES)) {
        const sizeDir = path.join(this.thumbnailDir, sizeKey);
        
        try {
          const files = await fs.readdir(sizeDir);
          let sizeTotal = 0;
          
          for (const file of files) {
            const filePath = path.join(sizeDir, file);
            const fileStat = await fs.stat(filePath);
            sizeTotal += fileStat.size;
          }
          
          stats.sizeBreakdown[sizeKey] = {
            count: files.length,
            size: sizeTotal
          };
          
          stats.totalThumbnails += files.length;
          stats.totalSize += sizeTotal;
          
        } catch (error) {
          // 忽略目录不存在的错误
          if (error instanceof Error && 'code' in error && error.code !== 'ENOENT') {
            console.error(`获取缩略图统计失败: ${sizeDir}`, error);
          }
        }
      }
    } catch (error) {
      console.error('获取缩略图统计信息失败:', error);
    }

    return stats;
  }

  /**
   * 检查文件是否存在
   */
  private async checkFileExists(filePath: string): Promise<void> {
    try {
      await fs.access(filePath);
    } catch (error) {
      throw new Error(`文件不存在: ${filePath}`);
    }
  }

  /**
   * 检查现有缩略图
   */
  private async checkExistingThumbnail(
    imagePath: string,
    thumbnailPath: string
  ): Promise<ThumbnailInfo | null> {
    try {
      // 检查缩略图文件是否存在
      const thumbnailStats = await fs.stat(thumbnailPath);
      const imageStats = await fs.stat(imagePath);

      // 检查缩略图是否比原始文件新
      if (thumbnailStats.mtime >= imageStats.mtime) {
        // 获取缩略图元数据
        const metadata = await sharp(thumbnailPath).metadata();
        
        return {
          path: thumbnailPath,
          size: Math.max(metadata.width || 0, metadata.height || 0),
          width: metadata.width || 0,
          height: metadata.height || 0,
          format: metadata.format || 'jpeg',
          filesize: thumbnailStats.size,
          createdAt: thumbnailStats.birthtime
        };
      }
    } catch (error) {
      // 缩略图不存在或无法访问
      return null;
    }

    return null;
  }

  /**
   * 生成路径哈希值
   */
  private generatePathHash(filePath: string): string {
    const crypto = require('crypto');
    return crypto.createHash('md5').update(filePath).digest('hex');
  }

  /**
   * 生成缓存键
   */
  private getCacheKey(
    imagePath: string,
    size: ThumbnailSize | number,
    format: string
  ): string {
    return `${imagePath}:${size}:${format}`;
  }

  /**
   * 获取缩略图目录路径
   */
  public getThumbnailDirectory(): string {
    return this.thumbnailDir;
  }

  /**
   * 获取支持的图片格式
   */
  public static getSupportedFormats(): string[] {
    return ['jpeg', 'png', 'webp', 'tiff', 'heic', 'heif'];
  }
}